home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / TIPS / FORMLINE.PAS < prev    next >
Pascal/Delphi Source File  |  1991-10-09  |  12KB  |  464 lines

  1. {************************************************}
  2. {                                                }
  3. {   Turbo Pascal for Windows                     }
  4. {   Formatted Input Edit Control Unit            }
  5. {   Copyright (c) 1991 by Borland International  }
  6. {                                                }
  7. {   by Jason Sprenger and John Wong              }
  8. {************************************************}
  9.  
  10. unit Formline;
  11.  
  12. interface
  13.  
  14. uses
  15.   WinTypes, WinProcs,
  16.   WObjects, Strings;
  17.  
  18. const
  19.   flPicOverflow = -2;
  20.   flError = -1;
  21.   flCharOk = 0;
  22.   flFormatOk = 1;
  23.   FormatSet = ['#', '?', '&', '@', '!', ';', '{', '}', '[', ']', '*'];
  24.  
  25. type
  26.   PFormEdit = ^TFormEdit;
  27.   TFormEdit = object(TEdit)
  28.     Picture: PChar;
  29.     constructor Init(AParent: PWindowsObject; AnId: Integer;
  30.       ATitle: PChar; X, Y, W, H, ATextLen: Integer; APicture: PChar);
  31.     constructor InitResource(AParent: PWindowsObject;
  32.       ResourceID, ATextLen: Word; APicture: PChar);
  33.     destructor Done; virtual;
  34.     procedure ChangePicture(APicture: PChar);
  35.     procedure WMSetFocus(var Message: TMessage);
  36.       virtual wm_First + wm_SetFocus;
  37.     procedure Store(var S: TStream); virtual;
  38.     procedure Load(var S: TStream); virtual;
  39.     function CanClose: Boolean; virtual;
  40.     procedure WMChar(var Message: TMessage);
  41.       virtual wm_First + wm_Char;
  42.     function CheckPicture(var Info: PChar; Pic: PChar;
  43.       var CPos, Resolved: Integer): Integer;
  44.   end;
  45.  
  46. implementation
  47.  
  48. constructor TFormEdit.Init;
  49. begin
  50.   TEdit.Init(AParent, AnID, ATitle, X, Y, W, H, ATextLen, false);
  51.   GetMem(Picture, 255);
  52.   StrCopy(Picture, APicture);
  53. end;
  54.  
  55. constructor TFormEdit.InitResource(AParent: PWindowsObject;
  56.   ResourceID, ATextLen: Word; APicture: PChar);
  57. begin
  58.   TEdit.InitResource(AParent, ResourceID, ATextLen);
  59.   Picture := StrNew(APicture);
  60. end;
  61.  
  62. destructor TFormEdit.Done;
  63. begin
  64.   StrDispose(Picture);
  65. end;
  66.  
  67. procedure TFormEdit.ChangePicture(APicture: PChar);
  68. begin
  69.   StrDispose(Picture);
  70.   Picture := StrNew(APicture);
  71. end;
  72.  
  73. procedure TFormEdit.WMSetFocus(var Message: TMessage);
  74. var
  75.   Text: PChar;
  76.   CPos, Resolved: Integer;
  77. begin
  78.   DefWndProc(Message);
  79.   GetMem(Text, 255);
  80.   GetText(Text, 255);
  81.   if StrLen(Text) = 0 then
  82.   begin
  83.     CPos := 0;
  84.     Resolved := 0;
  85.     CheckPicture(Text, Picture, CPos, Resolved);
  86.     if StrLen(Text) > 0 then
  87.     begin
  88.       SetText(Text);
  89.       CPos := StrLen(Text);
  90.       SetSelection(CPos + 1, CPos + 1);
  91.     end;
  92.   end;
  93. end;
  94.  
  95. procedure TFormEdit.Store(var S: TStream);
  96. begin
  97.   TEdit.Store(S);
  98.   S.StrWrite(Picture);
  99. end;
  100.  
  101. procedure TFormEdit.Load(var S: TStream);
  102. begin
  103.   TEdit.Load(S);
  104.   Picture := S.StrRead;
  105. end;
  106.  
  107. function TFormEdit.CanClose: Boolean;
  108. var
  109.   FirstText, NextText: PChar;
  110.   CPos, Dummy: Integer;
  111.   Result: Integer;
  112.   Resolved: Integer;
  113. begin
  114.   GetMem(FirstText, 255);
  115.   GetText(FirstText, 255);
  116.   if StrLen(FirstText) > 0 then  { don't perform validation if field is empty }
  117.   begin
  118.     GetMem(NextText, 255);
  119.     StrCopy(NextText, FirstText);
  120.     GetSelection(CPos, Dummy);
  121.     Result := CheckPicture(NextText, Picture, CPos, Resolved);
  122.     if Result = flFormatOk then
  123.     begin
  124.       CanClose := True;
  125.       if StrComp(FirstText, NextText) <> 0 then
  126.       begin
  127.         SetText(NextText);
  128.         SetSelection(CPos + 1, CPos + 1);
  129.       end
  130.     end
  131.     else
  132.     begin
  133.       CanClose := False;
  134.       SetText(FirstText);
  135.       SetSelection(CPos, CPos);
  136.       MessageBeep(0);
  137.       SetFocus(HWindow);
  138.     end;
  139.     FreeMem(NextText, 255);
  140.   end;
  141.   FreeMem(FirstText, 255);
  142. end;
  143.  
  144. function TFormEdit.Checkpicture(var Info: PChar; Pic: PChar;
  145.   var CPos, Resolved: Integer): Integer;
  146. var
  147.   InfoIndex, PicIndex: Integer;
  148.   Committed, MayCommit: Boolean;
  149.   Result: Boolean;
  150.  
  151.   function VariableResolution: Boolean;
  152.   var
  153.     Result: Boolean;
  154.   begin
  155.     Result := true;
  156.     if (PicIndex < StrLen(Pic)) and (InfoIndex < StrLen(Info)) then
  157.     begin
  158.       case Pic[PicIndex] of
  159.         '#':
  160.         begin
  161.           Result := Info[InfoIndex] in ['0'..'9'];
  162.           if Result then
  163.           begin
  164.             inc(PicIndex);
  165.             inc(InfoIndex);
  166.             inc(Resolved);
  167.           end;
  168.         end;
  169.  
  170.         '?':
  171.         begin
  172.           Result := Info[InfoIndex] in ['a'..'z','A'..'Z'];
  173.           if Result then
  174.           begin
  175.             inc(PicIndex);
  176.             inc(InfoIndex);
  177.             inc(Resolved);
  178.           end;
  179.         end;
  180.  
  181.         '&':
  182.         begin
  183.           Result := Info[InfoIndex] in ['a'..'z','A'..'Z'];
  184.           if Result then
  185.           begin
  186.             Info[InfoIndex]:=UpCase(Info[InfoIndex]);
  187.             inc(PicIndex);
  188.             inc(InfoIndex);
  189.             inc(Resolved);
  190.           end;
  191.         end;
  192.  
  193.         '@':
  194.         begin
  195.           Result := true;
  196.           inc(PicIndex);
  197.           inc(InfoIndex);
  198.           inc(Resolved);
  199.         end;
  200.  
  201.         '!':
  202.         begin
  203.           Result := true;
  204.           Info[InfoIndex] := UpCase(Info[InfoIndex]);
  205.           inc(PicIndex);
  206.           inc(InfoIndex);
  207.           inc(Resolved);
  208.         end;
  209.  
  210.         ';':
  211.         begin
  212.           inc(PicIndex);
  213.           Result := Info[InfoIndex] = Pic[PicIndex];
  214.           if Result then
  215.           begin
  216.             inc(PicIndex);
  217.             inc(InfoIndex);
  218.             inc(Resolved);
  219.           end;
  220.         end
  221.  
  222.         else
  223.         begin
  224.           Result := Info[InfoIndex] = Pic[PicIndex];
  225.           if Result then
  226.           begin
  227.             inc(PicIndex);
  228.             inc(InfoIndex);
  229.             inc(Resolved);
  230.           end;
  231.         end;
  232.       end;{ of case}
  233.     end;{ of if }
  234.     VariableResolution := Result;
  235.   end;{ of function VariableResolution }
  236.  
  237.   function DefaultResolution: Boolean;
  238.   var
  239.     Result: Boolean;
  240.   begin
  241.     Result := true;
  242.     if (PicIndex < StrLen(Pic)) and (InfoIndex < StrLen(Info)) then
  243.     begin
  244.       if (Info[InfoIndex] = ' ') and
  245.         not(Pic[PicIndex] in (FormatSet - [';'] )) then
  246.       begin
  247.         if Pic[PicIndex] = ';' then
  248.           inc(PicIndex);
  249.         Info[InfoIndex] := Pic[PicIndex];
  250.         inc(InfoIndex);
  251.         inc(PicIndex);
  252.         inc(Resolved);
  253.       end;
  254.     end;
  255.     DefaultResolution := Result;
  256.   end;
  257.  
  258.   function ConstantResolution: Boolean;
  259.   var
  260.     Result: Boolean;
  261.   begin
  262.     Result := true;
  263.     if (InfoIndex = StrLen(Info)) then
  264.     begin
  265.       while (PicIndex < StrLen(Pic)) and
  266.         not(Pic[PicIndex] in (FormatSet - [';'] + [','])) do
  267.       begin
  268.         if Pic[PicIndex] = ';' then
  269.           inc(PicIndex);
  270.         Info[StrLen(Info) + 1] := #0;
  271.         Info[StrLen(Info)] := Pic[PicIndex];
  272.         inc(InfoIndex);
  273.         inc(Resolved);
  274.         inc(PicIndex);
  275.         CPos := InfoIndex - 1;
  276.       end;
  277.     end;
  278.     ConstantResolution := Result;
  279.   end;
  280.  
  281.   function NextItem(Pic: PChar; PicIndex: Integer;
  282.     Terminator: Char): Integer;
  283.   var
  284.     GCount, OCount: Word;
  285.     NewIndex: Integer;
  286.   begin
  287.     GCount := 0;
  288.     OCount := 0;
  289.     NewIndex := PicIndex;
  290.     if Pic[NewIndex] <> Terminator then
  291.     repeat
  292.       case Pic[NewIndex] of
  293.       '{': inc(GCount);
  294.       '[': inc(OCount);
  295.       ';': inc(NewIndex);
  296.       '}': if GCount>0 then dec(GCount);
  297.       ']': if OCount>0 then dec(OCount);
  298.       end;
  299.       inc(NewIndex);
  300.     until ((GCount = 0) and (OCount = 0) and
  301.       (Pic[NewIndex] = Terminator)) or (NewIndex = StrLen(Pic));
  302.     NextItem := NewIndex;
  303.   end;
  304.  
  305.   function DetermineCommitment: Boolean;
  306.   var
  307.     TempIndex: Integer;
  308.   begin
  309.     if Result and MayCommit then
  310.     begin
  311.       MayCommit := false;
  312.       Committed := true;
  313.       TempIndex := NextItem(Pic, PicIndex, ',');
  314.       if (TempIndex < StrLen(Pic)) then
  315.         Pic[TempIndex-1] := #0;
  316.     end;
  317.     if not Result and not Committed then
  318.     begin
  319.       TempIndex := NextItem(Pic, PicIndex, ',');
  320.       if TempIndex < StrLen(Pic) then
  321.       begin
  322.         PicIndex := TempIndex + 1;
  323.         InfoIndex := 0;
  324.         Resolved := 0;
  325.         Result := true;
  326.       end;
  327.     end;
  328.     DetermineCommitment := Result;
  329.   end;
  330.  
  331.   function CanBeBlank(Pic: PChar; PicIndex: Integer): Boolean;
  332.   var
  333.     NewIndex: Integer;
  334.     TempPic: PChar;
  335.     Result: Boolean;
  336.   begin
  337.     GetMem(TempPic, StrLen(Pic) + 1);
  338.     Result := true;
  339.     while (PicIndex < StrLen(Pic)) and (Pic[PicIndex] <>',') and
  340.       Result do
  341.     begin
  342.       case Pic[PicIndex] of
  343.         '{':
  344.         begin
  345.           NewIndex := NextItem(Pic, PicIndex, '}');
  346.           StrCopy(TempPic, Pic);
  347.           TempPic[NewIndex] := #0;
  348.           TempPic := @TempPic[PicIndex + 1];
  349.           Result := CanBeBlank(TempPic, 1);
  350.           PicIndex := NewIndex + 1;
  351.         end;
  352.  
  353.         '[':
  354.         begin
  355.           NewIndex := NextItem(Pic, PicIndex, ']');
  356.           Result := true;
  357.           PicIndex := NewIndex + 1;
  358.         end;
  359.  
  360.         '*':
  361.         begin
  362.           if Pic[PicIndex + 1] in ['0'..'9'] then
  363.           begin
  364.             Result := true;
  365.             inc(PicIndex);
  366.             if Pic[PicIndex]='{' then
  367.             begin
  368.               PicIndex := NextItem(Pic, PicIndex, '}');
  369.               inc(PicIndex);
  370.             end
  371.             else inc(PicIndex);
  372.           end
  373.           else Result := false;
  374.         end
  375.         else Result := false;
  376.       end;
  377.     end;
  378.     CanBeBlank := Result;
  379.     FreeMem(TempPic, StrLen(Pic) + 1);
  380.   end;
  381.  
  382.   function CouldBeDone(Pic: PChar; PicIndex: Integer): Boolean;
  383.   var
  384.     TopPic, TempPic: PChar;
  385.   begin
  386.     GetMem(TempPic, StrLen(Pic) + 1);
  387.     TopPic := TempPic;
  388.     TempPic := @Pic[PicIndex];
  389.     CouldBeDone := CanBeBlank(TempPic, 1);
  390.     FreeMem(TopPic, StrLen(Pic) + 1);
  391.   end;
  392.  
  393.   function DetermineResult(CalcResult: Boolean): Integer;
  394.   var
  395.     Result: Integer;
  396.   begin
  397.     if CalcResult then
  398.       if CouldBeDone(Pic, PicIndex) then
  399.         if (InfoIndex = StrLen(Info)) then Result := flFormatOk
  400.         else Result := flPicOverflow
  401.       else Result := flCharOk
  402.     else Result := flError;
  403.     if (Result = flError) or (Result = flPicOverflow) then
  404.       CPos := InfoIndex;
  405.     DetermineResult := Result;
  406.   end;
  407.  
  408. begin
  409.   PicIndex := 0;
  410.   InfoIndex := 0;
  411.   MayCommit := true;
  412.   Committed := false;
  413.   repeat
  414.     DefaultResolution;  {Phase 2 Constant Resolution}
  415.     Result := VariableResolution;
  416.     if Result then
  417.       Result := ConstantResolution;  {Phase 1 Constant Resolution}
  418.     Result := DetermineCommitment;
  419.   until not Result  or (InfoIndex >= StrLen(Info)) or
  420.     (PicIndex >= StrLen(Pic));
  421.   CheckPicture := DetermineResult(Result);
  422. end;
  423.  
  424. procedure TFormEdit.WMChar(var Message: TMessage);
  425. var
  426.  FirstText, SecondText,  TopText, NextText: PChar;
  427.  Result, CPos, Resolved, Dummy: Integer;
  428. begin
  429.   if (Message.WParam >31) and (Message.WParam < 127) then
  430.   begin
  431.     GetMem(FirstText, 255);
  432.     GetMem(TopText, 255);
  433.     GetMem(SecondText, 255);
  434.     NextText := TopText;
  435.     GetText(FirstText, 255);
  436.     DefWndProc(Message);
  437.     GetText(NextText, 255);
  438.     StrCopy(SecondText, NextText);
  439.     GetSelection(CPos, Dummy);
  440.     Resolved:=0;
  441.     Result := CheckPicture(NextText, Picture, CPos, Resolved);
  442.     if (Result = flError) or (Result = flPicOverflow) then
  443.     begin
  444.       SetText(FirstText);
  445.       SetSelection(CPos, CPos);
  446.       MessageBeep(0);
  447.     end
  448.     else
  449.     begin
  450.       if StrComp(SecondText, NextText) <> 0 then
  451.       begin
  452.         SetText(NextText);
  453.         SetSelection(CPos + 1, CPos + 1);
  454.       end;
  455.     end;
  456.     FreeMem(FirstText, 255);
  457.     FreeMem(TopText, 255);
  458.     FreeMem(SecondText, 255);
  459.   end
  460.   else DefWndProc(Message);
  461. end;
  462.  
  463. end.
  464.